using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace WorldOnFire
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class WorldOnFire : Microsoft.Xna.Framework.Game
    {
        // XNA black magic
        GraphicsDeviceManager m_DeviceManager;
        SpriteBatch m_SpriteBatch;

        // Managers
        CStateManager m_StateManager;
        CRenderingManager m_RenderingManager;

        // Frame counter
        float fFPSTimeElapsed;
        int nFPSCounter;

        public WorldOnFire()
        {
            m_DeviceManager = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            // Let XNA do whatever the hell it does
            base.Initialize();

            // Turn off v-sync
            this.IsFixedTimeStep = false;

            // Initialize the event system
            SEventSystem.Initialize();

            // Initialize the managers
            m_StateManager = new CStateManager();
            m_StateManager.Initialize();

            m_RenderingManager = new CRenderingManager();
            m_RenderingManager.Initialize(m_DeviceManager, Content);

            // Set state stuff
            ABCState.SetStateManager(m_StateManager);
            ABCState.SetRenderingManager(m_RenderingManager);
            ABCState.SetSpriteBatch(m_SpriteBatch);
            ABCState.SetContentManager(Content);
            ABCState.SetScreenCenter(new Vector2(
                0.5f * GraphicsDevice.Viewport.Width, 0.5f * GraphicsDevice.Viewport.Height));
            ABCMenu.SetGame(this);

            // Initialize the first state
            m_StateManager.Push(new CPlatformState());
            m_StateManager.Push(new CSkirmishState());

            // Load content
            this.LoadContent();
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            m_SpriteBatch = new SpriteBatch(GraphicsDevice);
        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            // Allows the game to exit
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                this.Exit();

            float fDeltaTime = (float)gameTime.ElapsedGameTime.TotalSeconds;

            // Frames per second
            ++nFPSCounter;
            fFPSTimeElapsed += fDeltaTime;
            if (fFPSTimeElapsed > 1.0f)
            {
                Window.Title = "World on Fire - " + nFPSCounter.ToString() + " FPS";
                nFPSCounter = 0;
                fFPSTimeElapsed = 0.0f;
            }

            // Check for input
            SInputManager.Update();

            // Update the rendering manager
            m_RenderingManager.Update(fDeltaTime);

            // Update the state manager
            m_StateManager.Input(fDeltaTime);
            m_StateManager.Update(fDeltaTime);

            SEventSystem.ProcessEvents();

            // Let XNA screw around
            base.Update(gameTime);
        }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            // Clear color on fire
            m_DeviceManager.GraphicsDevice.Clear(ClearOptions.Target | ClearOptions.DepthBuffer, Color.Red, 1.0f, 0);

            // Render the states
            m_StateManager.Render();
            m_RenderingManager.RenderPostProcessing();

            // Hopefully let XNA do absolutely nothing
            base.Draw(gameTime);
        }
    }
}
